using System.ComponentModel.DataAnnotations;

namespace JGSY.CMS.LowCode.Platform.Infrastructure.Configuration.Models;

/// <summary>
/// 安全配置
/// </summary>
public class SecurityConfiguration
{
    public bool EnableMFA { get; set; } = true;
    public bool EnableThreatDetection { get; set; } = true;
    public bool DeviceFingerprintEnabled { get; set; } = true;
    
    [Required]
    [MinLength(32, ErrorMessage = "CSRF secret must be at least 32 characters long")]
    public string CsrfSecret { get; set; } = string.Empty;
    
    [Required]
    public string AppName { get; set; } = "CMS LowCode Platform";
    
    [Required]
    public string TotpIssuer { get; set; } = "CMS Platform";
    
    [Required]
    [MinLength(32, ErrorMessage = "Session secret must be at least 32 characters long")]
    public string SessionSecret { get; set; } = string.Empty;
    
    [Range(300, int.MaxValue, ErrorMessage = "Session timeout must be at least 5 minutes (300 seconds)")]
    public int SessionTimeout { get; set; } = 86400; // 24 hours
    
    [Range(1, 100, ErrorMessage = "Max login attempts must be between 1 and 100")]
    public int MaxLoginAttempts { get; set; } = 5;
    
    [Range(60, int.MaxValue, ErrorMessage = "Lockout duration must be at least 1 minute (60 seconds)")]
    public int LockoutDuration { get; set; } = 900; // 15 minutes
    
    [Range(6, 128, ErrorMessage = "Password minimum length must be between 6 and 128")]
    public int PasswordMinLength { get; set; } = 6;
    
    public bool RequireStrongPassword { get; set; } = true;
    
    public JwtSecurityConfiguration Jwt { get; set; } = new();
    public RateLimitSecurityConfiguration RateLimit { get; set; } = new();
}

/// <summary>
/// JWT 安全配置
/// </summary>
public class JwtSecurityConfiguration
{
    [Required]
    [MinLength(32, ErrorMessage = "JWT secret key must be at least 32 characters long")]
    public string SecretKey { get; set; } = string.Empty;
    
    [Required]
    public string Issuer { get; set; } = "JGSY.CMS.LowCode.Platform";
    
    [Required]
    public string Audience { get; set; } = "JGSY.CMS.LowCode.Platform.Client";
    
    [Range(5, 1440, ErrorMessage = "Token expiry must be between 5 minutes and 24 hours")]
    public int ExpiryMinutes { get; set; } = 60;
}

/// <summary>
/// 速率限制安全配置
/// </summary>
public class RateLimitSecurityConfiguration
{
    public bool EnableRateLimit { get; set; } = true;
    public List<RateLimitRuleConfiguration> GeneralRules { get; set; } = new()
    {
        new() { Endpoint = "*", Period = "1m", Limit = 100 }
    };
}

/// <summary>
/// 速率限制规则配置
/// </summary>
public class RateLimitRuleConfiguration
{
    [Required]
    public string Endpoint { get; set; } = "*";
    
    [Required]
    public string Period { get; set; } = "1m";
    
    [Range(1, int.MaxValue, ErrorMessage = "Rate limit must be greater than 0")]
    public int Limit { get; set; } = 100;
}

/// <summary>
/// CORS 配置
/// </summary>
public class CorsConfiguration
{
    public bool Enabled { get; set; } = true;
    
    [Required]
    public string Origin { get; set; } = "http://localhost:3000";
    
    public List<string> AllowedOrigins { get; set; } = new();
    public List<string> AllowedMethods { get; set; } = new() { "GET", "POST", "PUT", "DELETE", "OPTIONS" };
    public List<string> AllowedHeaders { get; set; } = new() { "*" };
    public bool AllowCredentials { get; set; } = true;
    public int PreflightMaxAge { get; set; } = 3600;
    
    /// <summary>
    /// 获取所有允许的源
    /// </summary>
    /// <returns>源列表</returns>
    public List<string> GetAllOrigins()
    {
        var origins = new List<string>();
        
        if (!string.IsNullOrEmpty(Origin))
        {
            origins.AddRange(Origin.Split(',', StringSplitOptions.RemoveEmptyEntries)
                                   .Select(o => o.Trim()));
        }
        
        origins.AddRange(AllowedOrigins);
        
        return origins.Distinct().ToList();
    }
}

/// <summary>
/// API 配置
/// </summary>
public class ApiConfiguration
{
    [Required]
    public string Prefix { get; set; } = "/api";
    
    public string Version { get; set; } = "v1";
    public bool EnableSwagger { get; set; } = true;
    public bool EnableVersioning { get; set; } = true;
    public int DefaultPageSize { get; set; } = 20;
    public int MaxPageSize { get; set; } = 100;
}

/// <summary>
/// 速率限制配置
/// </summary>
public class RateLimitConfiguration
{
    public bool Enabled { get; set; } = false;
    public int RequestsPerMinute { get; set; } = 100;
    public int RequestsPerHour { get; set; } = 1000;
    public int RequestsPerDay { get; set; } = 10000;
}

/// <summary>
/// 锁定配置
/// </summary>
public class LockedConfiguration
{
    public bool Enabled { get; set; } = false;
    public int MaxAttempts { get; set; } = 5;
    public int LockoutDurationMinutes { get; set; } = 15;
}

/// <summary>
/// 权限配置
/// </summary>
public class PermissionConfiguration
{
    public bool Enabled { get; set; } = false;
    public bool StrictMode { get; set; } = false;
    public List<string> DefaultRoles { get; set; } = new() { "User" };
    public List<string> AdminRoles { get; set; } = new() { "Admin", "SuperAdmin" };
    
    /// <summary>
    /// 是否启用基于数据库 Permission(Resource, Action -> Code) 的路由映射解析。
    /// </summary>
    public bool EnableDatabaseRouteMapping { get; set; } = false;

    /// <summary>
    /// 基于配置的 路径-方法 到 权限码 的映射集合，支持通配符。
    /// </summary>
    public List<PermissionRouteMapping> RouteMappings { get; set; } = new();
}

/// <summary>
/// 路由权限映射配置：Path 支持通配符 *（单段）与 **（跨段前缀）。
/// 例如：/api/users/**, /api/content/*/items
/// Methods: GET/POST/PUT/DELETE/… 映射到权限代码。
/// </summary>
public class PermissionRouteMapping
{
    [Required]
    public string Path { get; set; } = string.Empty;

    [Required]
    public Dictionary<string, string> Methods { get; set; } = new(StringComparer.OrdinalIgnoreCase);
}
